#include <pocketsphinx.h>
#include <pocketsphinx/endpointer.h>
#include <signal.h>
#include <stdlib.h>

static int global_done = 0;
static void catch_sig(int signum)
{
    (void)signum;
    global_done = 1;
}

int main()
{
    ps_decoder_t *decoder;
    ps_config_t *config;
    ps_endpointer_t *ep;
    FILE *recorder;
    short *frame;
    size_t frame_size;

    config = ps_config_init(NULL);
    ps_default_search_args(config);
    if ((decoder = ps_init(config)) == NULL)
        E_FATAL("PocketSphinx decoder init failed\n");

    if ((ep = ps_endpointer_init(0, 0.0, PS_VAD_MEDIUM_LOOSE, 16000, 0)) == NULL)
        E_FATAL("PocketSphinx endpointer init failed\n");

    recorder = popen("./test_record", "r");
    if (!recorder)
    {
        perror("open recorder error");
        return EXIT_FAILURE;
    }
    frame_size = ps_endpointer_frame_size(ep);
    if ((frame = malloc(frame_size * sizeof(frame[0]))) == NULL)
        E_FATAL_SYSTEM("Failed to allocate frame");
    if (signal(SIGINT, catch_sig) == SIG_ERR)
        E_FATAL_SYSTEM("Failed to set SIGINT handler");

    while (!global_done)
    {
        const int16 *speech;
        int prev_in_speech = ps_endpointer_in_speech(ep);
        size_t len, end_samples;
        if ((len = fread(frame, sizeof(frame[0]), frame_size, recorder)) != frame_size)
        {
            if (len > 0)
            {
                speech = ps_endpointer_end_stream(ep, frame, frame_size, &end_samples);
            }
            else
                break;
        }
        else
        {
            speech = ps_endpointer_process(ep, frame);
        }
        if (speech != NULL)
        {
            const char *hyp;
            if (!prev_in_speech)
            {
                printf("Speech start\n");
                ps_start_utt(decoder);
            }
            if (ps_process_raw(decoder, speech, frame_size, FALSE, FALSE) < 0)
                E_FATAL("ps_process_raw() failed\n");
            //if ((hyp = ps_get_hyp(decoder, NULL)) != NULL)
            //    fprintf(stderr, "PARTIAL RESULT: %s\n", hyp);
            if (!ps_endpointer_in_speech(ep))
            {
                printf("Speech end\n");
                ps_end_utt(decoder);
                if ((hyp = ps_get_hyp(decoder, NULL)) != NULL)
                    printf("%s\n", hyp);
            }
        }
    }
    free(frame);
    if (pclose(recorder) < 0)
        E_ERROR_SYSTEM("Failed to pclose(recorder)");
    ps_endpointer_free(ep);
    ps_free(decoder);
    ps_config_free(config);

    return 0;
}
